﻿using System;

namespace AlgorytmyGenetyczne.Kodowania
{
    public class KodowanieGraya : KodowanieBinarne
    {
        public KodowanieGraya(int dokladnosc, double poczatekDziedziny, double koniecDziedziny)
            : base(dokladnosc, poczatekDziedziny, koniecDziedziny)
        {
        }

        public override Genotyp koduj(object fenotyp)
        {
            bool[] geny = base.koduj(fenotyp).Geny;
            Genotyp genotyp = new Genotyp();
            genotyp.Geny = binarnyNaGray(geny);
            return genotyp;
        }

        public override object dekoduj(Genotyp genotyp)
        {
            Genotyp genotypBinarny = new Genotyp();
            genotypBinarny.Geny = grayNaBinarny(genotyp.Geny);
            return base.dekoduj(genotypBinarny);
        }

        private bool[] binarnyNaGray(bool[] reprezentacjaBinarna)
        {
            int dlugoscReprezentacji = reprezentacjaBinarna.Length;
            bool[] reprezentacjaGraya = new bool[dlugoscReprezentacji];
            reprezentacjaGraya[dlugoscReprezentacji-1] = reprezentacjaBinarna[dlugoscReprezentacji-1];

            for (int i = dlugoscReprezentacji-2; i > -1; i--)
            {
                reprezentacjaGraya[i] = reprezentacjaBinarna[i + 1] ^ reprezentacjaBinarna[i];
            }
            return reprezentacjaGraya;
        }

        private bool[] grayNaBinarny(bool[] reprezentacjaGraya)
        {
            int dlugoscReprezentacji = reprezentacjaGraya.Length;
            bool[] reprezentacjaBinarna = new bool[dlugoscReprezentacji];
            bool wartosc = reprezentacjaGraya[dlugoscReprezentacji - 1];
            reprezentacjaBinarna[dlugoscReprezentacji - 1] = wartosc;

            for (int i = dlugoscReprezentacji - 2; i > -1; i--)
            {
                if(reprezentacjaGraya[i])
                {
                    wartosc = !wartosc;
                }
                reprezentacjaBinarna[i] = wartosc;
            }

            return reprezentacjaBinarna;
        }
    }
}
